///////////////////////////////////////////////////////////////////////////////
//	FILENAME:	BilliardView.m 
//	SUMMARY:	Implementation of a Billiard-Ball View
//	SUPERCLASS:	View
//	INTERFACE:	None
//	PROTOCOLS:	None
//	AUTHOR:		Rohit Khare
//	COPYRIGHT:	(c) 1994 California Institure of Technology, eText Project
//	COPYRIGHT:	(c) 1992 Rohit Khare (core simulation code)
///////////////////////////////////////////////////////////////////////////////
//	DESCRIPTION
//		Separated out view from old BilliardView code.
///////////////////////////////////////////////////////////////////////////////
//	HISTORY
//	05/29/94:	Created as an eText Annotation.
//	1992-93:	Developed for CS20ab.
///////////////////////////////////////////////////////////////////////////////

#import "BBC.h"

@implementation BilliardView
- fillCache
{
	int i,j,left,bottom;
	NXPoint pt;

	[cacheGrid lockFocus];
	bottom = left = 0;
	i = y;
	while(i-- > 0){
		j = -1;
		while(++j < x){
			pt.x = left; pt.y = bottom;
			[Grid composite:NX_COPY toPoint:&pt];
			left += 20;
		}
		left = 0;
		bottom += 20;
	}
	[cacheGrid unlockFocus];
	return self;
}

- initFrame:(const NXRect *)nf
{	NXSize sz;

	[super initFrame:nf];
	Mucus = [NXImage findImageNamed:"Trail"];
	Wall  = [NXImage findImageNamed:"Wall"];
	Grid  = [NXImage findImageNamed:"Grid"];
	N = [NXImage findImageNamed:"N"];
	S = [NXImage findImageNamed:"S"];
	E = [NXImage findImageNamed:"E"];
	W = [NXImage findImageNamed:"W"];
	x = y = 10; sz.width = x * 20.0; sz.height = y * 20.0;
	cacheGrid = [[NXImage alloc] initSize:&sz];
    [cacheGrid setUnique:YES];	// this image must stay opaque!
    [cacheGrid setBackgroundColor:NX_COLORWHITE];
    [cacheGrid useCacheWithDepth:NX_DefaultDepth];
	[self fillCache];
	return self;
}
- setBBC:newBBC {theBBC = newBBC; return self;}
- setRes:(int) hres :(int) vres 
{	NXSize sz;

	//if ((x != hres) || (y != vres)) {
	x = hres; 	y = vres; 
	sz.width = x * 20.0; sz.height = y * 20.0;
	[cacheGrid setSize:&sz];
	[self fillCache];
	[self sizeTo:(x * 20.0) :(y * 20.0)];
	[self display];
	//}
	return self;
}
- drawSelf:(const NXRect *)rects :(int)rectCount {
	int i,j,left,bottom;
	char dir[2];
	NXPoint pt;
	char **state = [theBBC state];
//	BOOL isAccelerated = [theBBC isAccelerated];
	BOOL mucusMode = [theBBC doesShowPath];

	if (state == NULL) {return self;}
	if ([self isFocusView]) {
	[cacheGrid composite:NX_COPY toPoint:&(bounds.origin)];
	dir[1] = '\0';
	bottom = left = 0;
	i = y;
	while(i-- > 0){
		j = -1;
		while(++j < x){
			pt.x = left; pt.y = bottom;
			switch (state[i][j]) {	
				case ';':{	if(mucusMode) 
								[Mucus composite:NX_SOVER toPoint:&pt];
							break;}
				case 'O':{	[Wall composite:NX_SOVER toPoint:&pt];
							break;}
				case 'N':{	[N composite:NX_SOVER toPoint:&pt];
							break;}
				case 'S':{	[S composite:NX_SOVER toPoint:&pt];
							break;}
				case 'W':{	[W composite:NX_SOVER toPoint:&pt];
							break;}
				case 'E':{	[E composite:NX_SOVER toPoint:&pt];
							break;}
			}
			left += 20;
		}
		left = 0;
		bottom += 20;
	}
	}
	return self;
}

- mouseDown: (NXEvent *)ptr
{
	NXPoint	mloc,pt; int i,j; NXRect boundsy,sq;
	char **state = [theBBC state];
	
	if ((![[[NXApp inspector] currentObj] isKindOf:[BBCUI class]])  ||
		([[[NXApp inspector] currentObj] bbc] != theBBC)) {
		[[NXApp inspector] inspect:[[BBCUI new] setBBC:theBBC]];
		return self;
	}
	if (![theBBC isEditable]) return self;
	[self lockFocus];
	mloc = ptr->location;
	[self convertPoint:&mloc fromView:nil];
	[self getBounds:&boundsy];
	j = (int) floor((mloc.x / boundsy.size.width) * x);
	i = y - (int) floor((mloc.y / boundsy.size.height) * y);
	i--;
	if (i < 0) i = 0;
	pt.x = j * 20.0;
	pt.y = boundsy.size.height -  (i+1) * 20.0;
	if ((i <= y) && (j <= x)){ 
		switch (state[i][j]) {
			case ';':
			case '.':{	state[i][j] = 'O';
						[Wall composite:NX_COPY toPoint:&pt];
							break;}
			case 'O':{	state[i][j] = 'N';
						[N composite:NX_COPY toPoint:&pt];
							break;}
			case 'N':{	state[i][j] = 'S';
						[S composite:NX_COPY toPoint:&pt];
							break;}
			case 'S':{	state[i][j] = 'W';
						[W composite:NX_COPY toPoint:&pt];
							break;}
			case 'W':{	state[i][j] = 'E';
						[E composite:NX_COPY toPoint:&pt];
							break;}
			case 'E':{	state[i][j] = '.';
						sq.origin = pt; sq.size.height = sq.size.width = 20.0;
						PSsetgray(NX_WHITE);
						NXRectFill(&sq);
							break;}
		}
	}
	[self unlockFocus];
	[[self window] flushWindow];
	return self;
}
@end